package com.zhoug.mpchart.charts;

import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.graphics.Shader;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.animation.LinearInterpolator;

import com.zhoug.mpchart.R;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

/**
 * 自定义水平进度
 * ................................
 * .
 * .
 * .
 * ................................
 *
 * @Author: zhoug
 * @Date: 2024-07-30
 * @Description:
 */
public class MPHorizontalBar extends View {
    private static boolean DEBUG = true;
    private static final String TAG = ">>>MPHorizontalBar";
    private static int DEFAULT_WIDTH = 600;
    private static int DEFAULT_HEIGHT = 50;

    /**
     * 组件宽度固定为最大进度的长度
     */
    public static final int WIDTH_MODE_FIXED = 0;

    /**
     * 组件宽度为自适配:当前进度除以最大进度剩余最大进度长度
     */
    public static final int WIDTH_MODE_AUTO = 1;

    public static final int FILL_LAYOUT_WIDTH = -1;

    /**
     * 进度条颜色
     */
    protected int mForeColor;
    /**
     * 进度条颜色 渐变色开始色
     */
    protected int mForeStartColor;
    /**
     * 进度条颜色 渐变色结束色
     */
    protected int mForeEndColor;


    /**
     * 进度条最大值
     */
    protected int mMaxProgress;
    /**
     * 当前进度
     */
    protected int mProgress;


    /**
     * {@link  #WIDTH_MODE_FIXED,#WIDTH_MODE_AUTO}
     */
    protected int mWidthMode = WIDTH_MODE_FIXED;

    /**
     * 柱子顶部绘制圆弧
     */
    protected boolean mTopArc;


    /**
     * 画笔
     */
    protected Paint mPaint;
    /**
     * 路径
     */
    protected Path mPath = new Path();
    /**
     * 圆弧矩形
     */
    protected RectF mArcRect = new RectF();


    protected float mAnimValue = 1;
    /**
     * 动画
     */
    private ValueAnimator mAnimator;


    public MPHorizontalBar(Context context) {
        this(context, null);
    }

    public MPHorizontalBar(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, R.attr.mp_style_MPHorizontalBar);
    }

    public MPHorizontalBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs, defStyleAttr);
    }


    private void init(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.MPHorizontalBar, defStyleAttr, R.style.mp_style_MPHorizontalBar);
        mForeColor = a.getColor(R.styleable.MPHorizontalBar_mp_foreColor, Color.BLUE);
        mMaxProgress = a.getInt(R.styleable.MPHorizontalBar_mp_maxProgress, 100);
        mProgress = a.getInt(R.styleable.MPHorizontalBar_mp_progress, 0);
        mWidthMode = a.getInt(R.styleable.MPHorizontalBar_mp_widthMode, WIDTH_MODE_FIXED);
        mTopArc = a.getBoolean(R.styleable.MPHorizontalBar_mp_topArc, false);
        a.recycle();
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setColor(mForeColor);
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setStrokeWidth(1);


    }

    @SuppressLint("DrawAllocation")
    @Override
    protected void onDraw(@NonNull Canvas canvas) {
        super.onDraw(canvas);
        int width = getWidth();
        int height = getHeight();
        mPath.reset();
        float left = 0;
        float right;
        if (mWidthMode == WIDTH_MODE_FIXED) {
            right = width * 1.0f * mProgress / mMaxProgress;
        } else {
            right = width;
        }
        float top = 0;
        float bottom = height;
        if (mForeStartColor != 0 && mForeEndColor != 0) {
            mPaint.setShader(new LinearGradient(left, top, right, top,
                    mForeStartColor, mForeEndColor, Shader.TileMode.MIRROR));
        }
        if (mTopArc) {
            //顶部绘制圆弧
            //圆弧矩形的宽度
            float arcRectWidth = bottom - top;
            right -= arcRectWidth;
            mArcRect.left = right;
            mArcRect.right = mArcRect.left + arcRectWidth;
            mArcRect.top = top;
            mArcRect.bottom = bottom;
            if (right < left) {
                float temp = right;
                right = left;
                left = temp;
            }
            //矩形+圆弧
            mPath.moveTo(right, bottom);
            mPath.lineTo(left, bottom);
            mPath.lineTo(left, top);
            mPath.lineTo(right, top);
            mPath.arcTo(mArcRect, -90, 180, false);
            canvas.drawPath(mPath, mPaint);
        } else {
            //绘制矩形
            canvas.drawRect(left, top, right, bottom, mPaint);
        }


    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        if (DEBUG) {
            Log.d(TAG, "onMeasure:widthSize="+widthSize+",heightSize="+heightSize);
        }
        int measuredWidth = 0;
        switch (widthMode) {
            case MeasureSpec.EXACTLY:
                measuredWidth = widthSize;
                break;
            case MeasureSpec.AT_MOST:
                measuredWidth = Math.min(DEFAULT_WIDTH, widthSize);
                break;
            case MeasureSpec.UNSPECIFIED:
                measuredWidth = DEFAULT_WIDTH;
                break;
        }

        int measuredHeight = 0;
        switch (heightMode) {
            case MeasureSpec.EXACTLY:
                measuredHeight = heightSize;
                break;
            case MeasureSpec.AT_MOST:
                measuredHeight = Math.min(DEFAULT_HEIGHT, heightSize);
                break;
            case MeasureSpec.UNSPECIFIED:
                measuredHeight = DEFAULT_HEIGHT;
                break;
        }

        if (mWidthMode == WIDTH_MODE_FIXED) {
            setMeasuredDimension((int) (measuredWidth * mAnimValue), measuredHeight);
        } else {
            setMeasuredDimension((int) (measuredWidth * mAnimValue * mProgress / mMaxProgress), measuredHeight);
        }
    }


    public void setForeColor(int foreColor) {
        this.mForeColor = foreColor;
        mPaint.setColor(foreColor);
    }

    public void setGradientColor(int startColor, int endColor) {
        this.mForeStartColor = startColor;
        this.mForeEndColor = endColor;
    }

    public void setGradientColorNull() {
        this.mForeStartColor = 0;
        this.mForeEndColor = 0;
    }


    public void setMaxProgress(int maxProgress) {
        this.mMaxProgress = maxProgress;
    }

    public int getMaxProgress() {
        return mMaxProgress;
    }

    public void setProgress(int progress) {
        stopAnim();
        this.mProgress = progress;
    }

    public int getProgress() {
        return mProgress;
    }


    public void setWidthMode(int widthMode) {
        this.mWidthMode = widthMode;
    }

    public void setTopArc(boolean topArc) {
        this.mTopArc = topArc;
    }


    public void startAnim(int duration) {
        stopAnim();
        mAnimator = ValueAnimator.ofFloat(0.0f, 1.0f);
        mAnimator.setDuration(duration);
        mAnimator.setInterpolator(new LinearInterpolator());
        mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mAnimValue = (float) animation.getAnimatedValue();
                requestLayout();
            }
        });
        mAnimator.start();
    }

    public void stopAnim() {
        if (mAnimator != null) {
            mAnimator.cancel();
            mAnimator = null;
            mAnimValue = 1;
            requestLayout();
        }
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        stopAnim();
    }

    public void notifyData() {
        requestLayout();
    }

}
